package com.gframework.antibrush.limiter;

import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.scheduling.annotation.Scheduled;

/**
 * 单机内存存储的限流实现.
 * <p>此方法在受到分布式恶意攻击的情况下可能会造成OOM，建议使用redisson实现限流：{@link CurrentLimiterRedisson}
 * 
 * @since 1.0.0
 * @author Ghwolf
 */
@ConditionalOnMissingBean(CurrentLimiter.class)
public class CurrentLimiterLocal implements CurrentLimiter{
	/**
	 * 速率桶缓存，隔段时间会自动清空多余的
	 */
	private final Map<String,LeakyBucket> bucketCache = new ConcurrentHashMap<>();	
	
	@Override
	public boolean rate(LimitRequest anno, String key) {
		return bucketCache.computeIfAbsent(key, k -> new LeakyBucket(anno.timeUnit().toMillis(anno.time()), anno.maxRequest()))
				.requestPassage();
	}
	
	/**
	 * 1小时清空一次
	 * XXX 扩展为参数可配置
	 */
	@Scheduled(initialDelay=3600 * 1000,fixedDelay=3600 * 1000)
	protected void clear(){
		Iterator<Map.Entry<String, LeakyBucket>> iter = this.bucketCache.entrySet().iterator();
		while(iter.hasNext()) {
			if (iter.next().getValue().isFree()) {
				iter.remove();
			}
		}
	}

}
